package main

import (
	"fmt"
	"math"
)

type Shaper interface {
	Area() float32
}

type Square struct {
	side float32
}

func (sq *Square) Area() float32 {
	return sq.side * sq.side
}

type Rectangle struct {
	length, width float32
}

type Circle struct {
	radius float32
}

func (c *Circle) Area() float32 {
	return c.radius * c.radius * math.Pi
}

func (r *Rectangle) Area() float32 {
	return r.length * r.width
}

type stockPosition struct {
	ticker     string
	sharePrice float32
	count      float32
}

func (s stockPosition) getValue() float32 {
	return s.sharePrice * s.count
}

type car struct {
	make  string
	model string
	price float32
}

func (c car) getValue() float32 {
	return c.price
}

type valuable interface {
	getValue() float32
}

func showValue(asset valuable) {
	fmt.Printf("value of the asset is %v\n", asset.getValue())
}

func classifier(items ...interface{}) {
	for i, x := range items {
		switch x.(type) {
		case bool:
			fmt.Printf("Param #%d is a bool\n", i)
		case float64:
			fmt.Printf("Param #%d is a float64\n", i)
		case int, int64:
			fmt.Printf("Param #%d is a int\n", i)
		case nil:
			fmt.Printf("Param #%d is a nil\n", i)
		case string:
			fmt.Printf("Param #%d is a string\n", i)
		default:
			fmt.Printf("Param #%d is a unknown\n", i)

		}
	}
}

func main() {
	//sq1 := new(Square)
	//sq1.side = 5

	sq1 := Square{
		side: 5,
	}

	var areaIntf Shaper
	areaIntf = &sq1
	fmt.Printf("The square has area: %f\n", areaIntf.Area())

	if s, ok := areaIntf.(*Square); ok {
		fmt.Printf("The areaIntf is square! Area is %v\n", s.Area())
	}

	if s, ok := areaIntf.(*Circle); ok {
		fmt.Printf("The areaIntf is circle! Area is %v\n", s.Area())
	} else {
		fmt.Println("The areaIntf is not circle!!!")
	}

	r := Rectangle{
		5, 3,
	}

	areaIntf = &r
	fmt.Printf("The Rectange has area: %v\n", areaIntf.Area())

	var o valuable = stockPosition{"GOOG", 577.20, 4}
	showValue(o)
	o = car{"BMW", "M3", 66500}
	showValue(o)

	classifier(13, -14.3, "BELGIUM", complex(1, 2), nil, false)
}
